package ch.ethz.smseth.activity;

import java.util.ArrayList;
import java.util.LinkedList;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.telephony.gsm.SmsMessage;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import ch.ethz.smseth.ContactListAdapter;
import ch.ethz.smseth.ContactUtil;
import ch.ethz.smseth.Favorites;
import ch.ethz.smseth.R;
import ch.ethz.smseth.ContactUtil.Contact;
import ch.ethz.smseth.service.SenderService;

public class MainActivity extends Activity
{
	private static final int MENU_OPTIONS = 0;
	
	private static final int DIALOG_NO_CONNECTION = 1;
	private static final int DIALOG_NO_DESTINATION = 2;
	private static final int DIALOG_NO_MESSAGE = 3;
	
	public static final String PREFS_NAME = "name";
	public static final String PREFS_PW = "pw";
	public static final String PREFS_VALID = "valid";
	public static final String PREFS_SENDER = "senderPref";
	public static final String PREFS_SENDERS = "senders";
	public static final String PREFS_NOTIFY_PROGRESS = "notifyProgressPref";
	public static final String PREFS_NOTIFY_SENT = "notifySentPref";
	public static final String PREFS_AUTOHIDE_SENT = "autoHideSentPref";
	public static final String PREFS_TIMEOUT = "timeoutPref";
	
	private static final String BUNDLE_DESTINATIONS = "smsETH_destinations";
	private static final String BUNDLE_HINT_ALREADY_SHOWN = "smsETH_hintAlreadyShown";
	
	private AutoCompleteTextView _toText;
	private EditText _messageText;
	private Button _sendButton;
	private ViewGroup _toMultiline;
	private TextView _remainingCharactersText;
	
	private ArrayList<String> _destinations = new ArrayList<String>();
	private boolean _autoCompletionHintAlreadyShown;
	private SharedPreferences _prefs;
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		initFavoriteDb();
		
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.main);

		_toText = (AutoCompleteTextView) findViewById(R.id.toText);
		_messageText = (EditText) findViewById(R.id.messageText);
		_sendButton = (Button) findViewById(R.id.sendButton);
		_toMultiline = (ViewGroup) findViewById(R.id.toMultiline);
		_remainingCharactersText = (TextView) findViewById(R.id.remainingCharacters);
		
		ContactListAdapter adapter = new ContactListAdapter(this);
		_toText.setAdapter(adapter);
		_toText.setThreshold(1);
		
		_sendButton.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				send();
			}
		});
		
		_toText.setOnItemClickListener(new OnItemClickListener()
		{
			@Override
			public void onItemClick(AdapterView<?> arg0, View view, int arg2, long arg3)
			{
				_toText.setText("");
				addDestination((String) view.getTag());
			}
		});
		_toText.setOnFocusChangeListener(new OnFocusChangeListener()
		{
			@Override
			public void onFocusChange(View arg0, boolean arg1)
			{
				commitToText();
			}
		});
		_toText.addTextChangedListener(new TextWatcher()
		{
			
			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count)
			{
			}
			
			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after)
			{
			}
			
			@Override
			public void afterTextChanged(Editable s)
			{
				if (!_autoCompletionHintAlreadyShown && s.length() < 3 && onlyHasDigits(s.toString()))
				{
					Toast toast = Toast.makeText(MainActivity.this, "Hint: You can enter any contact name instead of the number.", Toast.LENGTH_LONG);
					toast.setGravity(Gravity.TOP, 0, 100);
					toast.show();
					_autoCompletionHintAlreadyShown = true;
				}
			}
		});
		
		_remainingCharactersText.setVisibility(View.INVISIBLE);
		_messageText.addTextChangedListener(new TextWatcher()
		{
			
			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count)
			{
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after)
			{
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void afterTextChanged(Editable s)
			{
				int[] calc = SmsMessage.calculateLength(s, false);
				int smsCount = calc[0];
				int remainingCharacters = calc[2];
				
				if (smsCount > 1 || remainingCharacters < 30)
				{
					_remainingCharactersText.setVisibility(View.VISIBLE);
					_remainingCharactersText.setText(remainingCharacters + " / " + smsCount);
				}
				else
				{
					_remainingCharactersText.setVisibility(View.INVISIBLE);
				}
			}
		});
		
		_prefs = PreferenceManager.getDefaultSharedPreferences(this);
		if (!_prefs.getBoolean(PREFS_VALID, false))
		{
			startActivity(new Intent(this, PreferencesActivity.class));
		}
		
		if (getIntent().getData() != null)
		{
			_toText.setText("");
			addDestination(getIntent().getData().getSchemeSpecificPart());
			_messageText.setText("");
		}
		else
		{
			_toText.setText("");
			_messageText.setText("");
		}
	}
	
	private void initFavoriteDb()
	{
		Favorites.initInstance(this);
		Favorites.getInstance().cleanUpFavorites();
	}
	
	private boolean onlyHasDigits(String text)
	{
		if (text.length() == 0) return false;
		for (int i = 0; i < text.length(); i ++)
		{
			char character = text.charAt(i);
			if (character > '9' || character < '0') return false;
		}
		return true;
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState)
	{
		super.onSaveInstanceState(outState);
		
		outState.putStringArrayList(BUNDLE_DESTINATIONS, _destinations);
		outState.putBoolean(BUNDLE_HINT_ALREADY_SHOWN, _autoCompletionHintAlreadyShown);
	}
	
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState)
	{
		super.onRestoreInstanceState(savedInstanceState);
		
		_autoCompletionHintAlreadyShown = savedInstanceState.getBoolean(BUNDLE_HINT_ALREADY_SHOWN, false);
		_destinations = savedInstanceState.getStringArrayList(BUNDLE_DESTINATIONS);
		recreateToTable();
	}
	
	private void commitToText()
	{
		if (_toText.getText().length() > 0)
		{
			addDestination(_toText.getText().toString());
			_toText.setText("");
		}
	}
	
	private void addDestination(String destination)
	{
		if (!_destinations.contains(destination)) _destinations.add(destination);
		recreateToTable();
	}
	
	private void removeDestination(String destination)
	{
		_destinations.remove(destination);
		recreateToTable();
	}
	
	private String getUserName(String destination)
	{
		Contact result = ContactUtil.get(this).fetchContactByNumber(destination);
		if (result != null) return result.name;
		else return destination;
	}
	
	private void send()
	{
		commitToText();
		
		if (_destinations.size() == 0)
		{
			showDialog(DIALOG_NO_DESTINATION);
		}
		else if (_messageText.getText().toString().length() == 0)
		{
			showDialog(DIALOG_NO_MESSAGE);
		}
		else
		{
			if (!isConnected())
			{
				showDialog(DIALOG_NO_CONNECTION);
			}
			else
			{
				for (String dest : getDestinationArray())
				{
					Favorites.getInstance().insertFavorite(dest);
				}
				
				Intent sendIntent = new Intent(this, SenderService.class);
				sendIntent.putExtra(SenderService.EXTRA_DEST, getDestinationArray());
				sendIntent.putExtra(SenderService.EXTRA_MESSAGE, _messageText.getText().toString());
				sendIntent.putExtra(SenderService.EXTRA_METHOD, SenderService.METHOD_ETH);
				startService(sendIntent);
				
				finish();
			}
		}
	}
	
	private String[] getDestinationArray()
	{
		String[] result = new String[_destinations.size()];
		for (int i = 0; i < _destinations.size(); i ++)
		{
			result[i] = _destinations.get(i);
		}
		return result;
	}
	
	private boolean isConnected()
	{
		ConnectivityManager conn = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		return conn.getActiveNetworkInfo() != null && conn.getActiveNetworkInfo().isConnectedOrConnecting();
	}
	
	protected Dialog onCreateDialog(int id)
	{
	    Dialog dialog;
	    AlertDialog.Builder builder = new AlertDialog.Builder(this);
	    switch(id)
	    {
	    case DIALOG_NO_CONNECTION:
	    	builder.setMessage("An internet connection is required to send an sms.")
	    	       .setCancelable(true)
	    	       .setPositiveButton("Settings", new DialogInterface.OnClickListener() {
	    	           public void onClick(DialogInterface dialog, int id) {
	    	        	   Intent intent = new Intent(Intent.ACTION_VIEW);
	    	        	   intent.setComponent(new ComponentName("com.android.settings", "com.android.settings.WirelessSettings"));
	    	               startActivity(intent);
	    	           }
	    	       })
	    	       .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
	    	           public void onClick(DialogInterface dialog, int id) {
	    	        	   dialog.dismiss();
	    	           }
	    	       }).setTitle("Connection required");
	    	dialog = builder.create();
	        break;
	    case DIALOG_NO_DESTINATION:
	    	builder.setMessage("No destination specified.")
	    	       .setCancelable(true)
	    	       .setPositiveButton("OK", new DialogInterface.OnClickListener() {
	    	           public void onClick(DialogInterface dialog, int id) {
	    	           }
	    	       })
	    	       .setTitle("Destination");
	    	dialog = builder.create();
	        break;
	    case DIALOG_NO_MESSAGE:
	    	builder.setMessage("No message specified.")
	    	       .setCancelable(true)
	    	       .setPositiveButton("OK", new DialogInterface.OnClickListener() {
	    	           public void onClick(DialogInterface dialog, int id) {
	    	           }
	    	       })
	    	       .setTitle("Message");
	    	dialog = builder.create();
	        break;
	    default:
	        dialog = null;
	    }
	    return dialog;
	}
	
	@Override
	public void onConfigurationChanged(Configuration newConfig)
	{
		super.onConfigurationChanged(newConfig);
	}
	
	@Override
	protected void onResume()
	{
		super.onResume();

		if (!_prefs.getBoolean(PREFS_VALID, false))
		{
			_toText.setEnabled(false);
			_messageText.setEnabled(false);
			_sendButton.setEnabled(false);
		} else
		{
			_toText.setEnabled(true);
			_messageText.setEnabled(true);
			_sendButton.setEnabled(true);
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		menu.add(0, MENU_OPTIONS, 0, R.string.options).setIcon(android.R.drawable.ic_menu_preferences);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		switch (item.getItemId())
		{
			case MENU_OPTIONS:
				startActivity(new Intent(this, PreferencesActivity.class));
				return true;
			default:
				return false;
		}
	}

	private void recreateToTable()
	{
		_toMultiline.setVisibility(View.INVISIBLE);
		_toMultiline.removeAllViews();
		LinkedList<String> remainingDestinations = new LinkedList<String>(_destinations);
		
		while (remainingDestinations.size() > 0)
		{
			LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
			params.setMargins(2, 2, 2, 2);
			LinearLayout layout = new LinearLayout(this);
			layout.addView(getDestinationView(remainingDestinations.poll()));
			_toMultiline.addView(layout, params);
		}
		
		_toMultiline.setVisibility(View.VISIBLE);
	}
	
	private View getDestinationView(String destination)
	{
		Button button = new Button(MainActivity.this);
		button.setText(getUserName(destination));
		button.setBackgroundResource(R.layout.my_button);
		button.setTextColor(Color.WHITE);
		button.setTextSize(17f);
		button.setMaxLines(1);
		button.setOnClickListener(new DestinationGridButtonClickListener(destination));
		return button;
	}
	
	public class DestinationGridButtonClickListener implements Button.OnClickListener
	{
		private String _dest;
		
		public DestinationGridButtonClickListener(String dest)
		{
			_dest = dest;
		}
		
		@Override
		public void onClick(View arg0)
		{
			MainActivity.this.removeDestination(_dest);
		}
	}

	public static final String[] FAVORITE_PROJECTION = new String[] { Favorites.ID, Favorites.NAME, Favorites.NUMBER, Favorites.TYPE };
}